5章 式と演算子
https://gyazo.com/51ba590422cb6160a4960060509a9941
評価(evaluate): 式について計算を実行すること
式は評価され、その結果として値(value)を持つ
let x, y;
y = x = 3 * 5;
次の順番で評価される
let x, y;
y = x = 3 * 5; // original
y = x = 15; // 掛け算が評価された
y = 15; // 1つ目の代入が評価され、xの値が15に。yはまだundefined.
15; // 2つ目の代入が評価され、yの値が15に。
// 結果は15になるが、この値は使われないので破棄される
JavaScriptのインタプリタが指揮を評価する順序は演算子ごとに決められている
5.1 演算子
演算子は非演算子の間で演算を行なって結果を生成する
5.2 算術演算子
減算と単項符号反転は同じ-
単行符号反転が先に評価される
const x = 5;
const y = 3 - -x; // y = 8
-が数値リテラルの前にある場合は数値リテラルの一部。演算子ではない。
+は文字列を数値に変換するのに使われることがある
const s = “5”;
console.log( 3 + s); // 35
console.log(3 + +s); // 8
剰余演算子%は結果の符号は非除数と同じになる
インクリメント演算子とデクリメント演算子は加算より先に評価される
5.3 演算子の優先順位
加減乗除や括弧は数学と同じ
算術演算子以外にも多くの演算子があるためルールも複雑
括弧は常に最優先される
5.4 比較演算子
5.4.1 厳密等価演算子と等価演算子
次のいずれかの場合は2つ値は厳密等価である
- 同じオブジェクトを参照しているとき
- プリミティブ型でデータ型も同じであるとき
厳密等価演算子===
厳密不等価演算子 !==
次のいずれかの場合は2つの値は等価である
- 同じオブジェクトを参照しているとき(したがって、厳密等価かつ等価)
- 同じ値に変換できるとき
等価演算子は混乱のもとになることがある
- 0と””は等価
等価演算子 ==
不等価演算子 !==
厳密等価演算子では望む結果が得られないことがわかる場合は型変換を行ってから比較をする。
等価演算子は使わない
順序があるデータ型でのみ使える
5.4.3 数値を比較する際の留意点
NaNはNaN自身を含め、どの値とも等しくならない
変数が数値かどうかを確認するときは組み込み関数のisNaN()を使う。
倍精度浮動小数点数は近似値であるため、倍精度の値を比較するのは注意
JavaScriptにはNumber.EPSILONという特殊な定数があり
これが2つの数値が等しいとみなすことができる差を表している
比較を緩くすることで無限ループを終了させることができる
文字列連結
+は足し算と文字列連結の2つを兼ねている(PerlやPHPでは.)
オペランドのデータ型から加算か文字列連結なのかを判断
加算も文字列連結も左から右へ評価される
各オペランドを検証し、いずれかが文字列なら文字列連結とみなす
両者が数値であれば加算
code:javascript
console.log(3 + 5 + "8"); // 88
console.log("3" + 5 + 8); // 358
5.6 論理演算子
true or false
JavaScriptでは論理値ではない値に対しても演算を行うことができ、論理値以外の値を返すこともできる
5.6.1 真と見なされる値と偽と見なされる値
falsyな値
undefined
null
false
0
NaN
'' (空文字列)
その他全てはtruthyな値
覚えておいたほうが良いtruthyな値
任意のオブジェクト
任意の配列(空配列も含む)
空白のみを含む文字列 " "
文字列 "false"
5.6.2 AND, OR, NOT
論理積:AND &&
論理和: OR ||
論理否定: NOT !
JavaScriptで排他的論理和XORを求める方法
(x || y) && x !== y
5.6.3 短絡評価
短絡評価(short-circuit evaluation): インタプリタが評価を簡略化すること
ANDは片方が偽なら結果も偽。
ORは片方が真なら結果も真。
code:javascript
const skipIt = true;
let x = 0;
const result = skipIt || x++; // xが評価されないため0のままになる
5.6.4 論理値ではない被演算子を用いた論理演算
論理値のオペランドを使っている場合は論理演算子は必ず論理値を返す。
オペランドが論理値ではない場合は結果を決めた値が返される。
table:ANDと論理値以外のオペランドの真理値表
x y x &&y
falthy falthy x(falthy)
falthy truthy x(falthy)
truthy falthy y(falthy)
truthy truthy y(falthy)
table:ORと論理値以外のオペランドの真理値表
x y x || y
falthy falthy y(falthy)
falthy truthy y(truthy)
truthy falthy x(truthy)
truthy truthy x(truthy)
便利な書き方
code:javascript
const options = suppliedOptions || { name: "デフォルト"}
// suppliedOptionsがオブジェクトなら真で評価終了。optionsに代入される
// suppliedOptionsがオブジェクトでないなら偽。次のオペランドのオブジェクトが評価されて代入される。
NOTは必ず論理値を返す
5.7 条件演算子
唯一の三項演算子
文ではなく式なので、他の式と組み合わせることができる。
code:javascript
const doIt = false;
const result = doIt ? "Did it!" : "Didn't it."
console.log(result); // Didn't do it.
5.8 カンマ演算子
,: 複数の式を組み合わせる
,は2つの式を評価して2つめの結果を返す。
複数の式を実行するが必要なのは値は最後の式の結果だけという場合に便利
,はどの演算子よりも優先順位が低い。
code:javascript
let x = 0, y = 10, z;
z = (x++, y++);
console.log(z); // 10
x = 0, y = 10;
z = x++, y++;
console.log(z); // 0
5.9 グループ化演算子
(...): 演算の順序を決める
5.10 ビット演算子
数値のそれぞれのビットに対して操作を行うことができる
読み飛ばし
5.11 typeof演算子
typeof: オペランドのデータ型を表す文字列返す
この演算子は7つのデータ型に正確に対応していない
typeof nullはobjectを返す(nullはプリミティブ)
配列オブジェクトと非配列オブジェクトを区別することがdけいない
5.12 void演算子
void: オペランドを評価してundefinedを返す
5.13 代入演算子
=: 値を変数に代入する。左辺は値を保存できるものである必要がある。(変数、プロパティ、配列要素)
定数への値の代入は厳密には宣言であって代入演算子ではない
連続代入可能
code:javascript
let v, v0;
v = v0 = 9.8; // v, v0はともに9.8
式の中で代入可能
code:javascript
let n, i=0;
while(i<nums.length && (n = numsi++) < 10) { console.log(10より小さい数字を発見: ${n});
}
演算と代入を一度に実行できる代入演算子がある
5.14 分割代入(デストラクチャリング)
ES2015から追加
オブジェクトの分割代入
変数名がオブジェクトのプロパティ名と一致しなければならない
code:javascript
const obj = { b: 2, c: 3, d: 4 };
const {a, b, c} = obj; // 分割代入
console.log(a); // undefined
console.log(b); // 2
console.log(c); // 3
console.log(d); // Refference Error: d is notdefined
代入と宣言を別々に行う場合、()で囲まないと{}がブロック文として解釈される
code:javascript
const obj = {b: 2, c: 3, d: 4 };
let a, b, c;
{a, b, c} = obj; // Syntax Error: Unexpected token =
({a, b, c} = obj); // 括弧で囲む必要がある
配列の分割では要素に対応して順番に代入できる
code:javascript
console.log(x); // 1
console.log(y); // 2
スプレッド演算子...を使えば残りの要素をすべて捕捉して新しい配列に代入することもできる
code:javascript
console.log(x); // 1
console.log(y); // 2
配列の分割代入を使うと変数の値を簡単に入れ替えることができる
code:javascript
let a = 5, b = 10;
console.log(a); // 10
console.log(b); // 5
5.15 オブジェクト演算子と配列演算子
オブジェクト、配列、関数については特別な演算子が用意されている。
.: メンバーアクセス演算子
[hoge]: 計算値によるメンバーアクセス(computed member access)
in: プロパティの有無を調べる
new: オブジェクトのインスタンスを作成
instanceof: プロトタイプチェインをテスト
...: スプレッド(展開)
delete: 削除
5.16 テンプレートリテラル内の式
${式}
5.17 式と制御フローのパターン
5.17.1 if...else文を条件演算子を使った構文に変換
code:javascript
// if...else文
if(isPrime(n)) {
label = '素数';
} else {
label = '非素数';
}
// 三項演算子
label = isPrime(n) ? '素数' : '非素数';
5.17.2 if文の短絡論理ORへの変換
結果が値になるif文も短絡論理OR式に変換できる。
code:js
// if文
if(!options) options = {};
// 短絡論理OR式
options = options || {};
5.18 まとめ